package main

import (
	"fmt"
	"net"
	"net/http"
	"strconv"
	"time"

	"gitee.com/jn-shao/common"
	"github.com/afex/hystrix-go/hystrix"
	grpcClient "github.com/asim/go-micro/plugins/client/grpc/v3"
	ratelimit "github.com/asim/go-micro/plugins/wrapper/ratelimiter/uber/v3"
	"github.com/asim/go-micro/plugins/wrapper/select/roundrobin/v3"
	opentracing2 "github.com/asim/go-micro/plugins/wrapper/trace/opentracing/v3"
	"github.com/asim/go-micro/v3"
	"github.com/asim/go-micro/v3/client"
	"github.com/asim/go-micro/v3/registry"
	"github.com/asim/go-micro/v3/server"
	"github.com/go-micro/plugins/v3/registry/consul"
	httpServer "github.com/go-micro/plugins/v3/server/http"
	"github.com/opentracing/opentracing-go"

	"routeApi/global"
	"routeApi/initialize"
	hystrix2 "routeApi/plugin/hystrix"
	go_micro_service_route "routeApi/proto/routeSrv"
)

func main() {

	//region 1.配置中心，存放经常变动的变量
	initialize.InitConfig()
	//endregion

	//region 2.注册中心
	consul := consul.NewRegistry(func(options *registry.Options) {
		options.Addrs = []string{
			global.ServerConfig.ConsulInfo.Host + ":" +
				strconv.FormatUint(global.ServerConfig.ConsulInfo.Port, 10),
		}
	})
	//endregion

	//region 3.添加链路追踪
	t, io, err := common.NewTracer(global.ServerConfig.JaegerInfo.ServiceName,
		global.ServerConfig.JaegerInfo.Host+":"+strconv.FormatUint(global.ServerConfig.JaegerInfo.Port, 10))
	if err != nil {
		common.Error(err)
	}
	defer io.Close()
	opentracing.SetGlobalTracer(t)
	//endregion

	//region  4.添加熔断器
	hystrixStreamHandler := hystrix.NewStreamHandler()
	hystrix.ConfigureCommand(global.ServerConfig.HystrixInfo.Name, hystrix.CommandConfig{Timeout: 1000})
	hystrixStreamHandler.Start()
	//endregion

	//region  5.添加日志
	//1）需要程序日志打入到日志文件中
	//2）在程序中添加filebeat.yml 文件
	//3) 启动filebeat，启动命令 ./filebeat -e -c filebeat.yml
	fmt.Println("日志统一记录在根目录 micro.log 文件中，请点击查看日志！")
	//endregion

	//region 6.启动熔断监听程序
	go func() {
		//http://192.168.0.121:9092/turbine/turbine.stream
		//看板访问地址 http://127.0.0.1:9002/hystrix，url后面一定要带 /hystrix
		err = http.ListenAndServe(net.JoinHostPort("0.0.0.0",
			strconv.FormatUint(global.ServerConfig.HystrixInfo.Port, 10)), hystrixStreamHandler)
		if err != nil {
			common.Error(err)
		}
	}()
	//endregion

	//region 7.添加监控采集地址
	common.PrometheusBoot(int(global.ServerConfig.PrometheusInfo.Port))
	//endregion

	//region 8.创建服务
	//初始化 gin Validator翻译
	if err := initialize.InitTrans("zh"); err != nil {
		common.Fatal(err)
	}

	srv := httpServer.NewServer(
		func(options *server.Options) {
			options.Advertise = global.ServerConfig.Host + ":" +
				strconv.FormatUint(global.ServerConfig.Port, 10)
		},
		server.Name(global.ServerConfig.Name),
		server.Version("latest"),
	)
	mux := initialize.Routers()
	if err := srv.Handle(srv.NewHandler(mux)); err != nil {
		common.Fatal(err)
	}
	service := micro.NewService(
		//开启gin http server，自定义服务地址，且必须写在其它参数前面
		micro.Server(srv),
		//使用grpc client 访问 grpc server
		micro.Client(grpcClient.NewClient(client.RequestTimeout(time.Second*5))),
		//指定服务端口
		micro.Address(":"+strconv.FormatUint(global.ServerConfig.Port, 10)),
		//添加注册中心，
		micro.Registry(consul),
		micro.RegisterTTL(5),
		micro.RegisterInterval(5),
		//添加链路追踪
		micro.WrapHandler(opentracing2.NewHandlerWrapper(opentracing.GlobalTracer())),
		micro.WrapClient(opentracing2.NewClientWrapper(opentracing.GlobalTracer())),
		//作为客户端范围启动熔断
		micro.WrapClient(hystrix2.NewClientHystrixWrapper()),
		//添加限流
		micro.WrapHandler(ratelimit.NewHandlerWrapper(1000)),
		//添加负载均衡，轮询
		micro.WrapClient(roundrobin.NewClientWrapper()),
	)

	service.Init()

	global.RouteService = go_micro_service_route.NewRouteService("routeSrv", service.Client())

	// 启动服务
	if err := service.Run(); err != nil {
		common.Fatal(err)
	}
	//endregion
}
